package casia.isiteam.springbootshiro.properties.shiro;

import casia.isiteam.springbootshiro.properties.other.ConfigurationItem;
import casia.isiteam.springbootshiro.properties.other.HttpState;
import casia.isiteam.springbootshiro.util.EncodeUtil;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.crypto.hash.Sha384Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.stereotype.Component;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * Author wzy
 * Date 2017/7/31 19:04
 */
public class ShiroPwdCustom  extends SimpleCredentialsMatcher {

    //集群中可能会导致出现验证多过5次的现象，因为AtomicInteger只能保证单节点并发
    private Cache<String, AtomicInteger> passwordRetryCache;

    public ShiroPwdCustom(CacheManager cacheManager) {
        passwordRetryCache = cacheManager.getCache("passwordRetryCache");
    }

    public boolean doCredentialsMatch(AuthenticationToken authcToken, AuthenticationInfo info) {
        UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
        String username = (String)token.getPrincipal();
//        System.out.println(getSessionTimeout());
//        System.out.println(config.getPreventImpact().get(HttpState.PREVENTIMPACT_NUMBER.reasonPhrase()));
        /*if( (boolean)config.getPreventImpact().get( Custom.PREVENTIMPACT_SWITCH.getNAME() )  ){
            //防止暴力冲击 retry count + 1
            AtomicInteger retryCount = passwordRetryCache.get(username);
            if(null == retryCount) {
                retryCount = new AtomicInteger(0);
                passwordRetryCache.put(username, retryCount);
            }
            int retrycount = retryCount.incrementAndGet();
            if(retrycount > (Integer) config.getPreventImpact().get( Custom.PREVENTIMPACT_NUMBER.getCODE() ) ) {
                throw new ExcessiveAttemptsException("username: " + username + " tried to login more than 5 times in period");
            }
            boolean matches = super.doCredentialsMatch(token, info);
            if(matches) {
                passwordRetryCache.remove(username); //clear retry data
            }else {
                throw new IncorrectCredentialsException(String.valueOf( (Integer) config.getPreventImpact().get( Custom.PREVENTIMPACT_NUMBER.getCODE() )-retrycount ));
            }
            return  matches;
        }
        boolean matches = super.doCredentialsMatch(token, info);
        return matches;*/


        AtomicInteger retryCount = passwordRetryCache.get(username);
        if(null == retryCount) {
            retryCount = new AtomicInteger(0);
            passwordRetryCache.put(username, retryCount);
        }
        int retrycount = retryCount.incrementAndGet();
        if(retrycount > 20 ) {
            throw new ExcessiveAttemptsException("username: " + username + " tried to login more than 5 times in period");
        }
        boolean matches = super.doCredentialsMatch(token, info);
        if(matches) {
            passwordRetryCache.remove(username); //clear retry data
        }else {
            throw new IncorrectCredentialsException(String.valueOf( 20 - retrycount ));
        }
        return  matches;
    }

    //加密
    public static String encrypt(String data) {
//        String sha384Hex = new Sha384Hash(data).toBase64();//sha348
        String base64 = EncodeUtil.getBase64(new StringBuilder(data).reverse().toString()); //base64
        return base64;
    }
}
